package com.fenqing.utils;

import com.fenqing.bean.ListNode;
import com.fenqing.bean.Node;
import com.fenqing.bean.TreeNode;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author fenqing
 */
public class EncoderFactory {

    /**
     * 单例
     */
    private static class SingletonHolder {
        private static final EncoderFactory INSTANCE = new EncoderFactory();
    }

    private EncoderFactory() {
    }

    /**
     * 获取解码器
     * @param parameterizedType 参数化类型
     * @return 解码器
     */
    public Encoder<String, ?> getEncoder(Type parameterizedType) {
        if (parameterizedType instanceof Class) {
            Class<?> clazz = (Class<?>) parameterizedType;
            return getEncoderByClass(clazz);
        } else if (parameterizedType instanceof ParameterizedType){
            ParameterizedType parameterizedType1 = (ParameterizedType) parameterizedType;
            return getEncoderByParameterizedType(parameterizedType1);
        }
        throw new RuntimeException("未找到对应的解析器");
    }

    private Encoder<String, ?> getEncoderByClass(Class<?> clazz) {
        if (clazz == TreeNode.class) {
            return new StringToTreeNodeEncoder();
        }  else if(clazz == ListNode.class) {
            return new StringToListNodeEncoder();
        } else if (clazz == String.class) {
            return new StringToStringEncoder();
        } else if (clazz == int[].class) {
            return new StringToIntArrayEncoder();
        } else if (clazz == char[].class) {
            return new StringToCharArrayEncoder();
        } else if (clazz == String[].class) {
            return new StringToStringArrayEncoder();
        } else if (clazz == char[][].class) {
            return new StringToCharTwoArrayEncoder();
        } else if (clazz == int[][].class) {
            return new StringToIntTwoArrayEncoder();
        } else if (clazz == int.class) {
            return new StringToIntEncoder();
        } else if (clazz == double.class) {
            return new StringToDoubleEncoder();
        } if (clazz == Node.class) {
            return new StringToNodeEncoder();
        }
        throw new RuntimeException("未找到对应的解析器");
    }

    private Encoder<String, ?> getEncoderByParameterizedType(ParameterizedType type) {
        Class<?> rawType = (Class<?>) type.getRawType();
        Type[] actualTypeArguments = type.getActualTypeArguments();
        //如果是list
        if (rawType == List.class && actualTypeArguments.length == 1) {
            Type type1 = actualTypeArguments[0];
            return getEncoderByListType(type1);
        }
        throw new RuntimeException("未找到对应的解析器");
    }

    private Encoder<String, ?> getEncoderByListType(Type type) {
        if (type instanceof Class) {
            Class<?> clazz = (Class<?>) type;
            if (clazz == Integer.class) {
                return new StringToIntListEncoder();
            }
        }
        throw new RuntimeException("未找到对应的解析器");
    }

    /**
     * 获取解析器
     */
    public static EncoderFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
